import { defineStore } from 'pinia';
// 导入UUID用于生成唯一文件ID（需安装uuid库：npm install uuid）
import { v4 as uuidv4 } from 'uuid';

let socket = null;
export const useWebRtcStore = defineStore('webrtc', {
  state: () => ({
    // 用户列表（从服务器获取）
    userList: [],
    // 连接映射: { targetUserId: { pc: RTCPeerConnection, status: 'connecting'|'connected'|'failed' } }
    connections: {},
    // 当前用户ID（前端生成或服务器分配）
    currentUserId: null,
    // 新增：管理文件传输状态 { fileId: { 文件名、总分片数、已接收分片等 } }
    fileTransfers: {},
    // 传输进度 { fileId: 进度百分比 }
    transferProgress: {},
    // 保活定时器
    keepAliveInterval: null,
    onMessage: null
  }),
  actions: {
    // 初始化：监听信令消息
    init (socketClient, onMessage, onReceiveProgress) {
      socket = socketClient;
      this.onMessage = onMessage;
      this.currentUserId = socket.id;
      this.onReceiveProgress = onReceiveProgress;
      // 保存当前用户ID
      localStorage.setItem('userId', this.currentUserId);
    },

    setUserList (userList) {
      this.userList = userList
    },

    // 发起连接：向目标用户ID建立WebRTC连接
    async connectTo ({ targetUserId, roomCode }) {
      if (this.connections[targetUserId]) {
        console.log('已存在与该用户的连接');
        return;
      }

      // 1. 创建RTCPeerConnection实例（使用自己的coturn服务器）
      const pc = new RTCPeerConnection({
        iceServers: [
          {
            urls: 'turn:www.hzrggdkj.com:3478',  // 自己的TURN
            username: 'xg',
            credential: 'Xg@2020+'
          }
        ],
        // 强制仅使用中继候选者（忽略内网候选者）
        // iceTransportPolicy: 'relay'  // 关键：只接受relay类型候选者
      });

      // 2. 存储连接状态
      this.connections[targetUserId] = {
        pc,
        status: 'connecting'
      };

      // 3. 监听ICE候选者（生成后发送给目标用户）
      pc.onicecandidate = (event) => {
        if (event.candidate) {
          socket.emit('signal', {
            room_code: roomCode, // 从房间状态中获取
            from_user: this.currentUserId,
            target_user: targetUserId,
            type: 'candidate',
            data: event.candidate
          });
        }
      };

      // 4. 监听连接状态变化
      pc.onconnectionstatechange = () => {
        switch (pc.connectionState) {
          case 'connected':
            this.connections[targetUserId].status = 'connected';
            console.log(`与${targetUserId}连接成功`);
            break;
          case 'failed':
            this.connections[targetUserId].status = 'failed';
            console.log(`与${targetUserId}连接失败`);
            break;
          case 'disconnected':
            this.connections[targetUserId].status = 'disconnected';
            console.log(`与${targetUserId}连接断开`);
            break;
        }
      };

      // 5. 创建数据通道（用于文件传输）
      const dataChannel = pc.createDataChannel('fileTransfer');
      this.setupDataChannel(dataChannel, targetUserId);

      // 6. 创建offer并发送给目标用户
      try {
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
        // 发送offer信令
        socket.emit('signal', {
          room_code: roomCode,
          from_user: this.currentUserId,
          target_user: targetUserId,
          type: 'offer',
          data: offer
        });
      } catch (e) {
        console.error('创建offer失败:', e);
        this.connections[targetUserId].status = 'failed';
      }
    },

    // 处理收到的信令
    async handleSignal (data) {
      const { from_user: senderId, type, data: signalData, room_code } = data;

      // 如果是首次收到该用户的信令，创建RTCPeerConnection
      if (!this.connections[senderId]) {
        const pc = new RTCPeerConnection({
          iceServers: [
            {
              urls: 'turn:www.hzrggdkj.com:3478',  // 自己的STUN/TURN
              username: 'xg',
              credential: 'Xg@2020+'
            }
          ]
        });
        this.connections[senderId] = { pc, status: 'connecting' };
        // 监听ICE候选者
        pc.onicecandidate = (event) => {
          if (event.candidate) {
            socket.emit('signal', {
              room_code: room_code,
              from_user: this.currentUserId,
              target_user: senderId,
              type: 'candidate',
              data: event.candidate
            });
          }
        };

        // 监听连接状态
        pc.onconnectionstatechange = () => {
          switch (pc.connectionState) {
            case 'connected':
              this.connections[senderId].status = 'connected';
              console.log(`与${senderId}连接成功`);
              break;
            case 'failed':
              this.connections[senderId].status = 'failed';
              console.log(`与${senderId}连接失败`);
              break;
            case 'disconnected':
              this.connections[senderId].status = 'disconnected';
              console.log(`与${senderId}连接断开`);
              break;
          }
        };

        // 监听对方创建的数据通道
        pc.ondatachannel = (event) => {
          this.setupDataChannel(event.channel, senderId);
        };
      }

      const pc = this.connections[senderId].pc;

      // 处理不同类型的信令
      switch (type) {
        case 'offer':
          await pc.setRemoteDescription(new RTCSessionDescription(signalData));
          const answer = await pc.createAnswer();
          await pc.setLocalDescription(answer);
          // 发送answer给对方
          socket.emit('signal', {
            room_code: room_code,
            from_user: this.currentUserId,
            target_user: senderId,
            type: 'answer',
            data: answer
          });
          break;

        case 'answer':
          await pc.setRemoteDescription(new RTCSessionDescription(signalData));
          break;

        case 'candidate':
          const candidate = new RTCIceCandidate(signalData);
          console.log(candidate)
          await pc.addIceCandidate(candidate);
          break;
      }
    },



    // 配置数据通道（用于文件传输）
    setupDataChannel (channel, userId) {
      // 关键配置：指定接收二进制数据的类型为ArrayBuffer
      channel.binaryType = 'arraybuffer';
      channel.onopen = () => {
        console.log(`与${userId}的数据通道已打开`);
        // 每30秒发送一个空的保活包
        // this.keepAliveInterval = setInterval(() => {
        //   if (channel.readyState === 'open') {
        //     channel.send(JSON.stringify({ type: 'keep_alive' }));
        //   }
        // }, 30000);
      };

      channel.onmessage = (event) => {

        // 区分消息类型：字符串（元数据）或二进制（文件分片）
        if (typeof event.data === 'string') {
          // 处理元数据（JSON字符串）
          const data = JSON.parse(event.data);
          console.log(`收到${userId}的消息:`, data);
          if (data.type === 'file_metadata') {
            this.onMessage(data);
            this.initFileTransfer(data);
          }
        } else {
          // 处理二进制文件分片（ArrayBuffer）
          this.handleBinaryChunk(event.data);
        }
      };
      channel.onerror = (error) => {
        console.log(error)
        console.error(`与${userId}的数据通道错误:`, {
          message: error.message,
          code: error.code,
          detail: error.errorDetail,
          channelState: channel.readyState, // 打印通道当前状态（open/connecting/closed）
          bufferedAmount: channel.bufferedAmount // 打印缓冲区大小
        });
      }
      channel.onclose = (e) => {
        // clearInterval(this.keepAliveInterval);
        console.log(`与${userId}的数据通道已关闭`);
      };

      // 存储数据通道到连接信息中
      this.connections[userId].dataChannel = channel;
    },

    // 断开与目标用户的连接
    disconnectFrom (targetUserId) {
      const conn = this.connections[targetUserId];
      if (conn) {
        conn.pc.close();
        delete this.connections[targetUserId];
      }
    },



    // 发送文件（优化版：二进制传输）
    sendFile ({ targetUserId, file, onBeginSend, onSendProgress }) {
      const conn = this.connections[targetUserId];
      if (!conn || conn.status !== 'connected' || !conn.dataChannel) {
        console.log('连接未就绪，请先建立连接');
        return;
      }
      const fileName = file.name;
      const chunkSize = 128 * 1024;// 2 * 1024 * 1024; // 2MB分片（可根据网络调整）
      const totalChunks = Math.ceil(file.size / chunkSize);
      // 生成唯一文件ID和基础配置
      const fileId = uuidv4();
      onBeginSend({
        fileId,
        fileName,
        totalChunks,
        fileSize: file.size
      })



      // 1. 先发送文件元数据（仍用JSON字符串，因为是小数据）
      conn.dataChannel.send(JSON.stringify({
        type: 'file_metadata',
        fileId,
        fileName,
        totalChunks,
        fileSize: file.size,
        userId: this.currentUserId
      }));

      // 2. 分片读取并发送二进制数据（核心优化点）
      const sendNextChunk = (chunkIndex) => {
        if (chunkIndex >= totalChunks) {
          console.log(`文件 ${fileName} 发送完成`);
          return;
        }

        const start = chunkIndex * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const fileSlice = file.slice(start, end);

        const reader = new FileReader();
        reader.onload = (e) => {
          const buffer = this.createBinaryPacket({
            fileId,
            chunkIndex,
            data: e.target.result
          });

          // 发送当前分片
          conn.dataChannel.send(buffer);

          // 更新进度
          this.transferProgress[fileId] = Math.round(((chunkIndex + 1) / totalChunks) * 100);
          onSendProgress({
            fileId,
            fileName,
            totalChunks,
            fileSize: file.size,
            progress: this.transferProgress[fileId]
          })


          // 关键：检查缓冲区剩余字节，动态决定下一次发送时机
          const checkBufferAndSendNext = () => {
            // 当缓冲区剩余字节 < 512KB 时，继续发送下一分片（阈值可调整）
            if (conn.dataChannel.bufferedAmount < 512 * 1024) {
              sendNextChunk(chunkIndex + 1);
            } else {
              // 缓冲区未满，10ms 后再检查
              setTimeout(checkBufferAndSendNext, 10);
            }
          };

          // 立即检查缓冲区状态，决定是否发送下一分片
          checkBufferAndSendNext();
        };
        reader.readAsArrayBuffer(fileSlice);
      };

      // 开始发送第一个分片
      sendNextChunk(0);
    },

    // 构造二进制数据包（头部+数据）
    createBinaryPacket ({ fileId, chunkIndex, data }) {
      // 文件ID用UUIDv4（36字符），转为UTF-8编码的ArrayBuffer
      const fileIdBuffer = new TextEncoder().encode(fileId);

      // chunkIndex用4字节无符号整数存储（最大支持42亿分片，足够用）
      const chunkIndexBuffer = new Uint32Array([chunkIndex]).buffer;

      // 总头部长度 = fileId长度(36字节) + chunkIndex长度(4字节)
      const headerLength = fileIdBuffer.byteLength + chunkIndexBuffer.byteLength;

      // 创建总缓冲区：头部 + 实际数据
      const totalBuffer = new ArrayBuffer(headerLength + data.byteLength);
      const totalView = new Uint8Array(totalBuffer);

      // 写入头部
      totalView.set(new Uint8Array(fileIdBuffer), 0); // 0-35字节：fileId
      totalView.set(new Uint8Array(chunkIndexBuffer), fileIdBuffer.byteLength); // 36-39字节：chunkIndex

      // 写入实际分片数据
      totalView.set(new Uint8Array(data), headerLength);

      return totalBuffer;
    },

    // 初始化文件传输状态（元数据处理）
    initFileTransfer (metadata) {
      this.fileTransfers[metadata.fileId] = {
        fileName: metadata.fileName,
        totalChunks: metadata.totalChunks,
        receivedChunks: {},
        fileSize: metadata.fileSize,
        userId: metadata.userId
      };
      this.transferProgress[metadata.fileId] = 0;
      console.log(`开始接收文件：${metadata.fileName}`);
    },

    // 处理二进制分片（核心优化点）
    handleBinaryChunk (buffer) {
      // 解析头部：前36字节是fileId（UUID），接下来4字节是chunkIndex（Uint32）
      const fileIdBuffer = buffer.slice(0, 36);
      const chunkIndexBuffer = buffer.slice(36, 40);
      const dataBuffer = buffer.slice(40); // 剩余部分是实际文件数据

      // 从缓冲区解析fileId和chunkIndex
      const fileId = new TextDecoder().decode(fileIdBuffer);
      const chunkIndex = new Uint32Array(chunkIndexBuffer)[0];

      // 保存分片数据
      const transfer = this.fileTransfers[fileId];
      if (!transfer) {
        console.warn(`未找到文件ID: ${fileId} 的传输记录`);
        return;
      }

      transfer.receivedChunks[chunkIndex] = dataBuffer;

      // 更新进度
      const progress = Math.round((Object.keys(transfer.receivedChunks).length / transfer.totalChunks) * 100);
      this.transferProgress[fileId] = progress;
      this.onReceiveProgress({
        fileId,
        progress
      })

      // 所有分片接收完成，合并文件
      if (Object.keys(transfer.receivedChunks).length === transfer.totalChunks) {
        this.mergeFileChunks(fileId);
      }
    },

    // 合并文件分片（逻辑不变，但处理的是原始二进制）
    mergeFileChunks (fileId) {
      const transfer = this.fileTransfers[fileId];
      if (!transfer) return;

      // 按索引排序分片并合并
      const chunks = [];
      for (let i = 0; i < transfer.totalChunks; i++) {
        chunks.push(transfer.receivedChunks[i]);
      }

      // 合并为Blob并触发下载
      const blob = new Blob(chunks);
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = transfer.fileName;
      a.click();

      // 清理资源
      URL.revokeObjectURL(url);
      delete this.fileTransfers[fileId];
      delete this.transferProgress[fileId];
      console.log(`文件 ${transfer.fileName} 接收完成`);
    },
  }
});
